package processus;
import interfaces.*;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;




/**
 * Classe du processus Processus_1 
 */

public class Processus_1 extends Thread{

	/** Nom du serveur de communication */
    public String comServerName = "SERVER_COMM";

    /** L'objet serveur de communication */
    public CommServerInterface comServer; 
    
    /** Nom des serveurs de synchronisation */
    public String transServerName = "sync1";
    
    /** Objets serveurs de communication */
    public SynchroServerInterface synchServer;
    
    /** Etat courant d'un processus  (place où se trouve le jeton) */
    public String etatCourant;
    
    /** Mapping entre les états du processus et les entiers (plus simple de travailler avec des entiers) */
    public HashMap<String,Integer> etatProcessus = new  HashMap<String,Integer> ();
    
    /** places où doit démarrer chaque instance */
    public String[] instances = {"P1_1"};
    
    /** nombre d'instances du processus */
    public static int nbThreads = 1;
    
    /** Temporisation a faire dans les méthodes */
    public static int TIME = 1000;
    
    /** Constructeur du processus */    
	public Processus_1(int rang) throws RemoteException, NotBoundException{
    	
		/** localiser le serveur de nommage (rmi Registry) */
        Registry registry = LocateRegistry.getRegistry("127.0.0.1");
    
        /** localiser le serveur de places de communications */
        comServer= (CommServerInterface)registry.lookup("SERVER_COMM");
  
        /** localiser le serveur de transistions de synchronisation */
        synchServer = (SynchroServerInterface)registry.lookup("sync");
        
        /** mapping des nom de d'états (places) en entiers */
        etatProcessus.put(new String("P1_1"),1);
        etatProcessus.put(new String("P1_2"),2);
        etatProcessus.put(new String("P1_3"),3);
        
        /** initialiser l'état du processus courant */
        etatCourant = instances[rang];
	}
	
	/* Méthodes représenatant les transitions locales */

	/* Méthodes représentant les transitions de synchronisation */
	public String method_sync() throws RemoteException, InterruptedException {
		System.out.println("Processus_1 : demande au serveur de synchronisation" );
		boolean tr = synchServer.synchronize();
		Thread.sleep((int)Math.random()*10 %3 * 1000);
		if (tr) {
			System.out.println("Processus_1 : transition réussie : " + etatCourant + " --------sync ----> P1_3" );
			return "P1_3";
		} else {
			System.out.println("Processus_1 : transition échec   : " + etatCourant + " --------sync ----> " + etatCourant);
			return etatCourant;
		}
	}

	/* Méthodes representant les transitions interagissant avec des places de communications */	
	public String method_P1_T2() throws RemoteException, InterruptedException {
		System.out.println("Processus_1 : transition (comm_places) : " + etatCourant + " --------P1_T2 --> P1_1" );
		Thread.sleep((int)Math.random()*10 %3 * 1000);
		comServer.produceTokens("Mutex", 1);
		return "P1_1";
	}

	public String method_P1_T1() throws InterruptedException, RemoteException {
		System.out.println("Processus_1 : demande au serveur de communication" );
		Thread.sleep((int)Math.random()*10 %3 * 1000);
		boolean tr = comServer.consumeTokens("Mutex" ,1);
			
			if (tr) {
				System.out.println("Processus_1 : transition réussie :" + etatCourant + " --------P1_T1  --> P1_2");
				return "P1_2";
			}
			else {
				System.out.println("Processus_1 : transition echouée :" + etatCourant + " --------P1_T1  ----> " + etatCourant);
				return etatCourant;
			}
	}

	
	
	/** Code exécuté par chaque processus 
	 * @throws InterruptedException */
	public void run() {

		while (true) {
			switch (etatProcessus.get(etatCourant)) {
			case 1: {
				try {
					//System.out.println("Processus_1 : etat : " + etatCourant );
					etatCourant = method_P1_T1();
				} catch (RemoteException e) {
					System.err.println("Erreur lors de la tentative de commnication avec le gestionnaire des ressources ");
					e.printStackTrace();
				} catch (InterruptedException e) {
					System.err.println("Erreur dans la demande de synchronisation");
					e.printStackTrace();
				}
				break;
			}
			case 2: {
				try {
					//System.out.println("Processus_1 : etat : " + etatCourant );
					etatCourant = method_sync();
				} catch (RemoteException e) {
					System.err.println("Erreur lors de la tentative de commnication avec le gestionnaire de la synchro");
					e.printStackTrace();
				} catch (InterruptedException e) {
					System.err.println("Erreur dans la demande de synchronisation");
					e.printStackTrace();
				}
				break;
			}
			case 3: {
				try {
					//System.out.println("Processus_1 : etat : " + etatCourant );
					etatCourant = method_P1_T2();
				} catch (RemoteException e) {
					System.err.println("Erreur lors de la tentative de commnication avec le gestionnaire des ressources ");
					e.printStackTrace();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				break;
			}
			}
		}
	}
}
